package com.stox.charting.ui.swing.model.price;

import java.util.ArrayList;
import java.util.List;

import com.stox.charting.ui.swing.event.listener.BackupDataChangedEventListener;
import com.stox.charting.ui.swing.event.listener.BarSpanChangedEventListener;
import com.stox.charting.ui.swing.event.listener.BarTypeChangedEventListener;
import com.stox.charting.ui.swing.event.listener.ChartSpanChangedEventListener;
import com.stox.charting.ui.swing.event.listener.HasBarsChangedEventListener;
import com.stox.charting.ui.swing.event.listener.MinimumSpanDataChangedEventListender;
import com.stox.charting.ui.swing.model.BarSpan;
import com.stox.charting.ui.swing.model.BarType;
import com.stox.charting.ui.swing.model.ChartModel;
import com.stox.charting.ui.swing.model.ChartSpan;
import com.stox.charting.ui.swing.model.Viewport;
import com.stox.charting.ui.swing.model.uiUnit.AbstractUiUnit;
import com.stox.charting.ui.swing.model.uiUnit.CandleStickUiUnit;
import com.stox.charting.ui.swing.model.uiUnit.EquiVolumeUiUnit;
import com.stox.charting.ui.swing.model.uiUnit.HLCUiUnit;
import com.stox.charting.ui.swing.model.uiUnit.LinePriceUiUnit;
import com.stox.charting.ui.swing.model.uiUnit.OHLCUiUnit;
import com.stox.charting.ui.swing.scheme.color.DefaultColorScheme;
import com.stox.core.model.IBar;
import com.stox.core.model.intf.HasBars;
import com.stox.ioc.Container;

public class PriceChartModel<T extends IBar> extends ChartModel<T> {

	private HasBars hasBars;
	private BarType barType;
	private final IBarViewport<T> ibarViewport;
	private List<T> backupData = new ArrayList<T>();
	private List<T> minimumBarSpanData = new ArrayList<T>();
	private ChartSpan chartSpan;
	private BarSpan barSpan;
	
			
	public PriceChartModel(PriceChart<T> chart) {
		super(chart);
		
		this.ibarViewport = new IBarViewport<T>(this);
		super.colorScheme = new DefaultColorScheme<T>();
		addChartModelListener(Container.get(HasBarsChangedEventListener.class));
		addChartModelListener(Container.get(BackupDataChangedEventListener.class));
		addChartModelListener(Container.get(ChartSpanChangedEventListener.class));
		addChartModelListener(Container.get(BarSpanChangedEventListener.class));
		addChartModelListener(Container.get(BarTypeChangedEventListener.class));
		addChartModelListener(Container.get(MinimumSpanDataChangedEventListender.class));
	}
	
	@Override
	public Viewport<T> getViewport() {
		return ibarViewport;
	}
	
	public HasBars getHasBars() {
		return hasBars;
	}

	@Override
	public PriceChart<T> getChart() {
		return (PriceChart<T>)super.getChart();
	}
	
	public BarType getBarType() {
		return barType;
	}
	
	public void setBarType(BarType barType) {
		boolean fireChartModelChangedEvent = 
				barType != null && ((this.barType != null && !this.barType.equals(barType)) || this.barType == null);
		this.barType = barType;
		if(fireChartModelChangedEvent){
			fireChartModelChangedEvent("barType");
		}
	}
	
	public void setHasBars(HasBars hasBars) {
		boolean fireChartModelChangedEvent = 
				hasBars != null && ((this.hasBars != null && !this.hasBars.equals(hasBars)) || this.hasBars == null);
		this.hasBars = hasBars;
		if(fireChartModelChangedEvent){
			fireChartModelChangedEvent("hasBars");
		}
	}
	
	@Override
	public void constructUiUnits() {
		List<T> data = getData();
		if(data != null && !data.isEmpty()){
			List<AbstractUiUnit<T>> uiUnits = new ArrayList<AbstractUiUnit<T>>(data.size());
			switch(barType){
			case LINE : 
				for(int i = 0; i < data.size(); i++){
					uiUnits.add(new LinePriceUiUnit<T>(this, i));
				}
				break;
			case HLC :
				for(int i = 0; i < data.size(); i++){
					uiUnits.add(new HLCUiUnit<T>(this, i));
				}
				break;
			case OHLC : 
				for(int i = 0; i < data.size(); i++){
					uiUnits.add(new OHLCUiUnit<T>(this, i));
				}
				break;
			case CANDLESTICK :
				for(int i = 0; i < data.size(); i++){
					uiUnits.add(new CandleStickUiUnit<T>(this, i));
				}
				break;
			case EQUI_VOLUME :
				for(int i = 0; i < data.size(); i++){
					uiUnits.add(new EquiVolumeUiUnit<T>(this, i));
				}
				break;
			case POINT_AND_FIGURE:
			case SWING :
				throw new UnsupportedOperationException();
			}
			getViewport().setUiUnits(uiUnits);
		}
	}

	public IBarViewport<T> getIbarViewport() {
		return ibarViewport;
	}

	public BarSpan getBarSpan() {
		return barSpan;
	}

	public void setBarSpan(BarSpan barSpan) {
		boolean fireChartModelChangedEvent = 
				barSpan != null && ((this.barSpan != null && !this.barSpan.equals(barSpan)) || this.barSpan == null);
		this.barSpan = barSpan;
		if(fireChartModelChangedEvent){
			fireChartModelChangedEvent("barSpan");
		}
	}
	
	public ChartSpan getChartSpan() {
		return chartSpan;
	}

	public void setChartSpan(ChartSpan chartSpan) {
		boolean fireChartModelChangedEvent = 
				chartSpan != null && ((this.chartSpan != null && !this.chartSpan.equals(chartSpan)) || this.chartSpan == null);
		this.chartSpan = chartSpan;
		if(fireChartModelChangedEvent){
			fireChartModelChangedEvent("chartSpan");
		}
	}

	public List<T> getBackupData() {
		return backupData;
	}

	public void setBackupData(List<T> backupData) {
		boolean fireChartModelChangedEvent = 
				backupData != null && ((this.backupData != null && !this.backupData.equals(backupData)) || this.backupData == null);
		this.backupData = backupData;
		if(fireChartModelChangedEvent){
			fireChartModelChangedEvent("backupData");
		}
	}

	public List<T> getMinimumBarSpanData() {
		return minimumBarSpanData;
	}

	public void setMinimumBarSpanData(List<T> minimumSpanData) {
		boolean fireChartModelChangedEvent = 
				minimumSpanData != null && ((this.minimumBarSpanData != null && !this.minimumBarSpanData.equals(minimumSpanData)) || this.minimumBarSpanData == null);
		this.minimumBarSpanData = minimumSpanData;
		if(fireChartModelChangedEvent){
			fireChartModelChangedEvent("minimumSpanData");
		}
	}
}
